package com.heima.jvm.sjms;

import java.io.*;
import java.lang.reflect.Constructor;

/**
 * 设计模式： 编程套路。 一共有23种，常用的7,8种。
 *  单例模式：   一个类只产生一个对象，这一个对象在整个应用中是唯一的!
 *      1. 懒汉式
 *      2. 饿汉式
 *      3. 双检锁
 *
 *      4. 枚举单例
 *      5. 各种其他第三方中间件，例如：redis
 *
 *  工厂模式： Spring Bean工厂。核心作用：程序解耦，更灵活。
 *
 *  动态代理：
 *  策略模式：
 *  观察者模式：
 *  适配器模式：
 *  原型模式：
 */

public class Demo {
    private static  Student stu;

    public static void main(String[] args) throws Exception {

        new Thread(()->{
            Student stu2 = getStu();
            System.out.println("stu2 = " + stu2);
        }).start();

        Student stu1 = getStu();
        System.out.println("stu1 = " + stu1);


        //通过反射方式来破坏单例
        Class<? extends Student> clazz = stu1.getClass();
        Student stu3 = clazz.newInstance();
        System.out.println("stu3 = " + stu3);

        //通过序列化方式来破坏单例
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\IdeaProjects\\heima-leadnews\\heima-leadnews-test\\jvm-demo\\a.txt"));
        oos.writeObject(stu1);      //序列化
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\IdeaProjects\\heima-leadnews\\heima-leadnews-test\\jvm-demo\\a.txt"));
        Student stu4 = (Student) ois.readObject();      //反序列化
        ois.close();
        System.out.println("stu4 = " + stu4);


        System.out.println("-----------------枚举单例----------------");
        Obj o1 = Obj.stu;
        Obj o2 = Obj.stu;
        System.out.println(o1 == o2);

        /*枚举单例下：反射不能破坏*/
//        Class<? extends Obj> objClazz = o1.getClass();
//        Constructor<? extends Obj> constructor = objClazz.getDeclaredConstructor();
//        constructor.setAccessible(true);
//        Obj o3 = constructor.newInstance();
//        System.out.println(o1 == o3);

        /*枚举单例下，序列号不能破坏*/
        ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream("D:\\IdeaProjects\\heima-leadnews\\heima-leadnews-test\\jvm-demo\\a.txt"));
        oos1.writeObject(o1);      //序列化
        oos1.close();

        ObjectInputStream ois1 = new ObjectInputStream(new FileInputStream("D:\\IdeaProjects\\heima-leadnews\\heima-leadnews-test\\jvm-demo\\a.txt"));
        Obj o4 = (Obj) ois1.readObject();      //反序列化
        ois1.close();
        System.out.println(o1 == o4);

    }

    //懒汉式：真正要用的时候才来创建
    public static Student getStu(){
        synchronized ("abc") {
            if (stu == null){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                stu = new Student();
            }
        }
        return stu;
    }

    //饿汉式：提前创建好，要用的时候直接拿
    public static Student getStu1(){
        return stu;
    }
}


enum Obj implements Serializable{
    stu;

    private Obj(){}
}
